
	/************************************************************************************************
	
		Constructor: Interface

		Methods:
			i		Interface				(iid, data)		- sid: 2.0
			md	getMetaData			(id)					- sid: 2.0
			b		isImplementedBy	(obj)					- sid: 2.0
					
		Legend:
			data:								{ inherits, ... }
	
		MetaData:
			var, methods:				{ id, value, inherited, from } 
			interfaces:					[]<jsl.Interface>
		
		Note:
			The super interfaces var/method conflicts are resolved with a priority level assigned 
			from left(high) to right(low) 
			
	************************************************************************************************/

	//-------------------------------------------------------------------------------
	jsl.Interface = function(iid, data) {
		try {
			var obj, md, a, cx, iids, walker, body, name, id
			
			//@d[
			if(arguments.length !== 2) throw jsl.ParamError()//@d]
			
			if(this instanceof arguments.callee && !this.__created) {
				
				//@d[				
				jsl.validate(iid	, "qid"	, "iid")
				jsl.validate(data	, "o"		, "data")											
				if(jsl.Interface.__data[iid])	throw jsl.ParamError("AlreadyDefined:iid")//@d]

				//-------------------------------------------------------------------------------				
				if(iid.indexOf(".") !== -1) {
					
					iids	= iid.split(".")													
					obj = jsl.__go
					
					for(a = 0; a < iids.length - 1; obj = obj[iids[a]], a++) 				
						//@d[
						if(!jsl.isObject(obj[iids[a]]))	throw jsl.ParamError("BadValue:iid")//@d]
						;						
					
					cx = obj
				}
				else
					cx = jsl.__go
				
				md								= {}
				md["var"]					= []
				md["methods"]			= []
				md["interfaces"]	= []

				this.__md					= md
				this.__name 			= iid
				this.__cname			= "jsl.Interface"
				this.constructor	= this				
				this.__created		= true
								
				//-------------------------------------------------------------------------------				
				if(data.hasOwnProperty("inherits")) {
	
					obj	= jsl.isArrayLike(data.inherits) ? data.inherits : [ data.inherits ]
					iids = {}
					
					//@d[
					if(!obj.length) throw jsl.ParamError("EmptyArray:data.inherits")//@d]
					
					for(a = 0; a < obj.length; a++) {
						
						//@d[						
						name = obj[a].getName()

						jsl.validate(obj[a], "interface", "data.inherits[" + a + "]")
						if(iids.hasOwnProperty(name))	throw jsl.ParamError("AlreadyDefined:" + name)//@d]				
												
						md["interfaces"] 	= md["interfaces"].concat(obj[a], obj[a].getMetaData("interfaces"))//@d[
						iids[name] 				= true//@d]
					}
					
					//no sort, the order of the interfaces is an information								
					md["interfaces"] = jsl.__mlang.array_unique.call(md["interfaces"])
				}
				 								
				//@sys: Explorer v.8 	- args.callee + "" - > wrap the function into round brackets (function() {...})
				//@sys: Safari 4.04 	- every block comment remains and is terminated with ';' in string functions 
				for(id in data)
					if(data.hasOwnProperty(id) && id !== "inherits") {

						obj = { id: id, value: data[id], inherited: false, from: this }
						
						if(jsl.isFunction(data[id])) {

							body = jsl.__mlang.function_getBody.call(data[id])
							body = body.search(/[^;\s\n]/) !== -1							

							if(body)	md["var"].push(obj)
							else 			md["methods"].push(obj)
						}
						else 																									
							md["var"].push(obj)
					}
				
				if(data.hasOwnProperty("inherits")) {
					
					obj			= md["interfaces"]				
					walker	= function(id) { if(id < this.length) this[id].inherited = true }
					
					for(a = 0; a < obj.length; a++)	{						
						md["var"] 		= md["var"].concat			(jsl.Object.walk(obj[a].getMetaData("var")		, walker))
						md["methods"]	= md["methods"].concat	(jsl.Object.walk(obj[a].getMetaData("methods"), walker))
					}					
					
					md["var"] 		= jsl.__mlang.array_unique.call(md["var"]			, { rule: function(e1, e2) { return e1.id !== e2.id } })
					md["methods"]	= jsl.__mlang.array_unique.call(md["methods"]	, { rule: function(e1, e2) { return e1.id !== e2.id } })					
				}

				md["var"].sort			(function(v1, v2) { return v1.id <= v2.id ? -1 : 1 })
				md["methods"].sort	(function(v1, v2) { return v1.id <= v2.id ? -1 : 1 })

				return jsl.Interface.__data[iid] = cx[iid.slice(iid.lastIndexOf(".") + 1)] = this
			}
			else
				return new arguments.callee(iid, data)
		}
		catch(e) {
			jsl.throwError(e, jsl, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Interface.prototype = jsl.Object()
	//-------------------------------------------------------------------------------
	jsl.Interface.__name		= "jsl.Interface"	
	jsl.Interface.__data		= []	
	//-------------------------------------------------------------------------------
	jsl.Interface.prototype.getMetaData = function(id) {
		try {
			var v
			
			//@d[
			if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(id, "s+", "id")			
			if(!jsl.Object.isIn(id, "methods", "var", "interfaces"))	throw jsl.ParamError("BadValue:id:['methods' | 'var' | 'interfaces']")
			//@d]
			
			if(id == "methods") 	v = jsl.Object.clone(this.__md["methods"]	, 1)
			else if(id == "var")	v = jsl.Object.clone(this.__md["var"]			, 1)
			else									v = jsl.Object.clone(this.__md["interfaces"])
							
			return v
		}
		catch(e) { 
			jsl.throwError(e, this, arguments)
		}
	}
	//-------------------------------------------------------------------------------
	jsl.Interface.prototype.isImplementedBy = function(obj) {
		try {
			var a, rv, methods, vars, len, params, fparams, f
			
			//@d[
			if(arguments.length !== 1)	throw jsl.ParamError()
			jsl.validate(obj, "o", "obj")//@d]
						
			methods = this.getMetaData("methods")
			len			= methods.length
			rv 			= true
			
			//1° - methods
			for(a = 0; a < len && rv; a++) {
				
				f = obj[methods[a].id]
				
				if(jsl.isFunction(f)) {	 
				
					params 	= jsl.__mlang.function_getParameters.call(methods[a].value).join()
					fparams	= jsl.__mlang.function_getParameters.call(f).join()
					
					if(params != fparams)	rv = false
				}
				else 
					rv = false
			}
			
			//2° - vars
			if(rv) {
				vars 	= this.getMetaData("var")
				len		= vars.length
				
				for(a = 0; a < len && rv; a++) 
					rv = obj[vars[a].id] === vars[a].value
			}
							
			return rv
		}
		catch(e) {
			jsl.throwError(e, this, arguments)		
		}
	}
	
	//Interface init
	//-------------------------------------------------------------------------------
	jsl.Interface.__native 						= jsl.Object.__native.copy().merge(jsl.Interface.prototype)
	jsl.Interface.__native.__md				= undefined
	jsl.Interface.__native.__created	= undefined			
	jsl.Interface.__native.__data			= undefined
		
	